/*
一个用户态的文件操作系统调用接口类, 模拟用户态下的进程的文件打开表项, 文件读写偏移量, 以及通过文件句柄进行的增删查改操作
*/
#ifndef FILE_API
#define FILE_API

#include "DiskManager.h"
#include <cstddef>
#include <unordered_map>
#include <mutex>

// 用于定位lseek的宏
#define FILE_START 0
#define FILE_CUR 1
#define FILE_END 2

class FileApi{
public:
    // 文件打开表项结构体定义
    #pragma pack(push, 1)
    struct FileTableItem{ 
        int inode_id; // inode节点id
        off_t offset; // 当前读写文件的偏移量
        mutable std::mutex mtx; // 文件项加锁保证多线程环境的读写

        // 有参构造函数
        FileTableItem(int inode_id_val, int offset_val) 
            : inode_id(inode_id_val), offset(offset_val) {
        }
        
        // 默认构造函数
        FileTableItem() : inode_id(-1), offset(0) {
        }
        
        // 拷贝构造函数
        FileTableItem(const FileTableItem& other) 
            : inode_id(other.inode_id), offset(other.offset) {
            // 注意：mutex不能拷贝，所以这里创建一个新的mutex
        }
        
        // 移动构造函数
        FileTableItem(FileTableItem&& other) noexcept
            : inode_id(other.inode_id), offset(other.offset) {
            // 移动构造，mutex不能移动，所以创建一个新的
        }
        
        // 拷贝赋值操作符
        FileTableItem& operator=(const FileTableItem& other) {
            if (this != &other) {
                inode_id = other.inode_id;
                offset = other.offset;
                // 不拷贝mutex
            }
            return *this;
        }
        
        // 移动赋值操作符
        FileTableItem& operator=(FileTableItem&& other) noexcept {
            if (this != &other) {
                inode_id = other.inode_id;
                offset = other.offset;
                // 不移动mutex
            }
            return *this;
        }
    };
    #pragma pack(pop)

    static FileApi& getInstance(); // 全局单例类
    ~FileApi(); // 析构函数

    int lseek(int fd, off_t offset, int whence); // 调整文件的读写偏移量
    int open(const std::string& path); // 打开文件, 获得文件句柄
    int read(int fd, void* buff, size_t size); // 从文件中读取数据到缓冲区
    int write(int fd, void* buff, size_t size); // 从缓冲区写入数据到文件
    int close(int fd); // 关闭一个打开的文件
    int del(int fd); // 删除文件
private:
    FileApi();
    static FileApi* instance_;
    std::unordered_map<int,FileTableItem> file_table; // 维护进程的文件打开表项
};

#endif